from xml.sax import make_parser
from xml.sax.handler import ContentHandler

import util
import bricks

def parse(pbfi_model_filename):
    parser = make_parser()   
    pbfi_descrition_handler = PBFIXmlHandler()
    parser.setContentHandler(pbfi_descrition_handler)
    pbfi_model_fp = open(pbfi_model_filename, 'r') 
    parser.parse(pbfi_model_fp)
    return (pbfi_descrition_handler.structure,pbfi_descrition_handler.context)

class PBFIXmlHandler(ContentHandler):
    def __init__(self):
        self.structure = bricks.Sequence("root","root")
        self.context = dict() 
        self.structures_stack = util.Stack()
        self.case_value = None
        self.in_file = False

    def startElement(self, name, attrs):
        if name == 'file':
            self.in_file = True
        elif self.in_file:
            var_id = attrs.get('id', None)
            var_name = attrs.get('name', None)
            brick = None 

            if name == 'int' or name == 'i32':
                brick = bricks.Integer(var_id,var_name)
            elif name == 'i16':
                brick = bricks.Integer(var_id,var_name,precision=16)
            elif name == 'i64':
                brick = bricks.Integer(var_id,var_name,precision=64)
            elif name == 'string':
                size = attrs.get('size', None)
                brick = bricks.String(var_id,var_name,padded=True,length=size)
            elif name == 'byte':
                brick = bricks.Byte(var_id,var_name)
            elif name == 'float' or name == 'f32':
                brick = bricks.Float(var_id,var_name)
            elif name == 'f64':
                brick = bricks.Float(var_id,var_name,precision=64)
            elif name == 'array':
                variable_count_id = attrs.get('count', None)
                brick = bricks.Array(var_id,var_name,bricks.Variable(variable_count_id,self.context))
            elif name == 'child':
                brick = bricks.Child(var_id,var_name)
            elif name == 'switch':
                switch_variable_id = attrs.get('on', None)
                brick = bricks.Switch(var_id,var_name,bricks.Variable(switch_variable_id,self.context))
            elif name == 'case':
                brick = bricks.Sequence(var_id,var_name)
                self.case_value = attrs.get('value', None) 

            if brick!=None:
                self.structures_stack.push(brick)
            return

    def endElement(self, name):
        if name == 'file':
            self.in_file = False
        else:
            brick = self.structures_stack.pop()
            if self.structures_stack.is_empty():
                self.structure.addBrick(brick)    
            else:
                if name == 'case':
                    self.structures_stack.top().addBrick(self.case_value,brick)
                    self.case_value = None
                else:
                    self.structures_stack.top().addBrick(brick)

